(in-package :netrisd)

(defconstant MAJOR_VERSION 1)
(defconstant PROTOCOL_VERSION 3)

(defvar *players* nil)

(defclass player ()
  ((name :accessor player-name :initarg :name :initform nil)
   (socket :accessor player-socket :initarg :socket)
   (opponent :accessor player-opponent :initarg :opponent :initform nil)))

(defmacro player-by (fn object)
  `(lambda (x) (eq (,fn x) ,object)))

(defun get-player (fn)
  (find-if fn *players*))

(defun add-player (socket)
  (let ((player (make-instance 'player :socket socket))
	(opponent (get-player (player-by player-opponent nil))))
    (push player *players*)
    (when opponent   
      (setf (player-opponent opponent) player) ;;gracz - ten, co sie dopiero co polaczyl    
      (setf (player-opponent player) opponent) ;;przeciwnik - ten, co czekal na gracza
      ;;wysylamy przeciwnikowi pakiet z wersja
      (write-packet (make-instance 'packet
				   :type NP_version
				   :size 12
				   :data (list 0 0 0 MAJOR_VERSION 0 0 0 PROTOCOL_VERSION)) ;;hardcoding jest brzydki, ale to najlepsze wyjscie w tym wypadku
		    (player-socket opponent))
      ;;odbieramy naglowek NP_startConn od przeciwnika i wysylamy graczowi 
      ;;pakiet z wersja i naglowek NP_startConn
      (let ((header (read-header (player-socket opponent))))
	(write-packet (make-instance 'packet
				     :type NP_version
				     :size 12
				     :data (list 0 0 0 MAJOR_VERSION 0 0 0 PROTOCOL_VERSION))
		      (player-socket player))
	(write-bytes header (player-socket player)))
      ;;odbieramy caly pakiet NP_startConn od gracza i odsylamy go przeciwnikowi
      (with-packets (initiate-connection) (player-socket player)
		    (write-packet initiate-connection (player-socket opponent)))
      ;;odbieramy reszte pakietu od przeciwnika i wysylamy go graczowi
      (write-bytes (read-bytes 12 (player-socket opponent)) (player-socket player))
      ;;gdy obaj gracze maja ustalonego przeciwnika, mozemy zaczac petle przekazywania
      (format t "robię wątki~%")
      (sb-thread:make-thread (lambda () (handle-events player)))
      (sb-thread:make-thread (lambda () (handle-events opponent))))))

(defun handle-events (player)
  (format t "Handluje eventy :)")
  (let ((socket (player-socket player)))
    (loop do
	 (with-packets (packet) socket
		       (write-packet packet (player-socket (player-opponent player)))))))
    

